package me.leon.ext.android

import android.app.Activity
import android.os.Bundle
import android.os.Parcelable
import java.io.Serializable
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

fun <T> Activity.extra(default: T, key: String = "") = ExtraData(this, key, default)

inline fun <reified T> Activity.extraArray(default: Array<T> = arrayOf(), key: String = "") =
    ExtraData(this, key, default)

fun <T> Activity.extraList(default: ArrayList<T> = arrayListOf(), key: String = "") =
    ExtraData(this, key, default)

@Suppress("IMPLICIT_CAST_TO_ANY")
class ExtraData<T>(val activity: Activity, private val key: String, private val default: T) :
    ReadOnlyProperty<Any?, T> {

    private val intent by lazy { activity.intent }

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return getExtra(findProperName(property))
    }

    private fun findProperName(property: KProperty<*>) = key.ifEmpty { property.name }

    private fun getExtra(key: String): T {

        return when (default) {
            is Byte -> intent.getByteExtra(key, default)
            is Char -> intent.getCharExtra(key, default)
            is Short -> intent.getShortExtra(key, default)
            is Int -> intent.getIntExtra(key, default)
            is Long -> intent.getLongExtra(key, default)
            is Float -> intent.getFloatExtra(key, default)
            is Double -> intent.getDoubleExtra(key, default)
            is Boolean -> intent.getBooleanExtra(key, default)
            is String -> intent.getStringExtra(key)
            is CharSequence -> intent.getCharSequenceExtra(key)
            is Serializable -> intent.getSerializableExtra(key)
            is Parcelable -> intent.getParcelableExtra(key)
            is Bundle -> intent.getBundleExtra(key)
            else -> throw IllegalArgumentException("Unsupported type.")
        } as
            T
    }
}
